package dingding;

import com.opencsv.CSVReader;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.taobao.api.ApiException;
import dingding.dao.PLC;
import dingding.dao.configInformation;
import org.mozilla.universalchardet.UniversalDetector;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;

public class dingdingAlarm {
    public static void main(String[] args) throws ApiException, UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
//            System.setOut(new PrintStream(System.out, true, "UTF-8"));
//        String currentDirectory = System.getProperty("user.dir");
//        String filePath =currentDirectory+ File.separator+ "dingdingSendConfig.ini";
        String filePath = Paths.get("").toAbsolutePath().resolve("dingdingSendConfig.ini").toString();
//        System.out.println(filePath);
        configInformation config = new configInformation();
        Map<String, String> keyValueMap = INIReader.readINIFile(filePath,config);
//            String file = "C:\\Users\\Administrator\\Desktop\\钉钉报警\\Alarm_log1.csv";//file path faultlist
//        System.out.println(keyValueMap);
        if(keyValueMap != null ) {
            config.setFile(keyValueMap.get("filepath"));
//            String plcNAME = "CPU_BA12/CPU_PBS3";
            String plcNAME = keyValueMap.get("plcName");
            config.setPlcNAME(plcNAME);
            config.setPlcLIST(plcNAME.split("/"));
            String classNAME = keyValueMap.get("MsgClass");
            config.setClassNAME(classNAME);
//                String[] classlist = classNAME.split("/");
            config.setClasslist(classNAME.split("/"));
            String faultNAME = keyValueMap.get("faults");
            config.setFaultNAME(faultNAME);
            config.setFaultlist(faultNAME.split("/"));
//                String[] faultlist = faultNAME.split("/");
            config.setWebhook(keyValueMap.get("webhook"));
            config.setSecret(keyValueMap.get("secret"));
//                String webhook = keyValueMap.get("webhook");
        }else{
//                config.setClasslist(new String[] );
        }
        MyGUI.GUI(config);
//            System.out.println("secret:  "+config.getSecret());
//            MyUtils.DingTalkExample(config,"大家好");

    }
}

// 工具类
class MyUtils {
    private void MyUtils() {
    }

    ;

    //    判断元素是否在列表中
    public static <E> boolean charinlist(E[] LIST, E e) {
        boolean contains = false;
        for (E element : LIST) {
            if (element.equals(e)) {
                contains = true;
                break;
            }
        }
        return contains;
    }

    ;

    //    判断日期是否跟当天一致
    public static boolean isdate(String dateString) {
        boolean bool = false;
        LocalDateTime currentDateTime = LocalDateTime.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        String formattedDateTime = dtf.format(currentDateTime);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        try {
//            Date date = sdf.parse(dateString.strip());
            Date date = sdf.parse(dateString.trim());  // 替换 strip() 为 trim()
            Date date2 = sdf.parse(formattedDateTime);
            if (date.equals(date2)) {
                bool = true;
//                System.out.println(date2);
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }
        return bool;
    }

    ;

    //    获取当前日期时间
    public static String getDate() {
        LocalDateTime currentDateTime = LocalDateTime.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        String formattedDateTime = dtf.format(currentDateTime);
        return formattedDateTime;
    }

    ;


    // 打印数组
    public static void soutArrary(List ARR) {
        String ms = "[";
        for (int i = 0; i < ARR.size(); i++) {
            if (i != 0) {
                ms = ms + ",";
            }
            ms = ms + ARR.get(i);
        }
        ms = ms + "]";
        System.out.println(ms);
    }

    public static void soutArrary(String[] ARR) {
        String ms = "[";
        for (int i = 0; i < ARR.length; i++) {
            if (i != 0) {
                ms = ms + ",";
            }
            ms = ms + ARR[i];
        }
        ms = ms + "]";
        System.out.println(ms);
    }

    // 获取文件编码格式
    public static String codeType(String filename) {
        String code = null;
        try {
            byte[] bytes = Files.readAllBytes(Paths.get(filename));
            UniversalDetector detector = new UniversalDetector(null);
            detector.handleData(bytes, 0, bytes.length);
            detector.dataEnd();
            String encoding = detector.getDetectedCharset();
            if (encoding != null) {
//                    System.out.println("Detected encoding: " + encoding);
                code = encoding;
            } else {
//                    System.out.println("Unable to detect encoding.");
            }
            detector.reset();
        } catch (IOException e) {
//                e.printStackTrace();
        }
        return code;

    }
    //    获取钉钉Token
    public static String getToken(String url,String AppKey,String AppSecret) throws RuntimeException {
        try {
            DefaultDingTalkClient client = new DefaultDingTalkClient(url);
            OapiGettokenRequest request = new OapiGettokenRequest();

            request.setAppkey(AppKey);
            request.setAppsecret(AppSecret);
            request.setHttpMethod("GET");
            OapiGettokenResponse response = client.execute(request);
            String accessToken = response.getAccessToken();
            return accessToken;
        } catch (ApiException e) {
            throw new RuntimeException();
        }

    }

}


// GUI界面
class MyGUI {

    public static void GUI(configInformation config) {
        final boolean[] runing = {false};
        ArrayList<String> fault1 = new ArrayList<>();
        ArrayList<String> reset1 = new ArrayList<>();
//        boolean[] onePass = {false};
        String encoding = MyUtils.codeType(config.getFile());
        config.setEncoding(encoding==null?"UTF-8":encoding);
        JFrame frame = new JFrame("钉钉故障报警");
        // 加载图标文件 图标使用png格式  存放在resource目录下
        ImageIcon icon = new ImageIcon(dingdingAlarm.class.getResource("/dingdingAlarm.png"));
        // 检查是否成功加载
        if (icon.getImageLoadStatus() != MediaTracker.COMPLETE) {
            System.err.println("图标加载失败！请检查路径或文件格式。");
        } else {
//            System.out.println("图标加载成功！");
            // 设置图标
            Image image = icon.getImage();
            frame.setIconImage(image);
        }
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(605, 850);

        // 创建一个JPanel对象
        JPanel panel = new JPanel(null);
//        panel.setLayout(new FlowLayout()); // 设置布局为流式布局
//        panel.setLayout(new GridLayout(10, 3));
        // 设置JPanel的背景颜色
//        panel.setBackground(Color.LIGHT_GRAY);
        panel.setBackground(new Color(219, 220, 221));
        // 设置字体
        Font font20 = new Font("宋体", Font.PLAIN, 20); // 设置字体为Arial，风格为普通，大小为16
        Font font16 = new Font("楷体", Font.PLAIN, 16); // 设置字体为Arial，风格为普通，大小为16

        // 创建按钮
        JButton buttonStart = new JButton("开始");
        buttonStart.setBounds(120, 535, 100, 30);
        JButton buttonEnd = new JButton("结束");
        buttonEnd.setBounds(340, 535, 100, 30);

        // 创建标签
        JLabel tipLabel = new JLabel("提示：同目录下的dingdingSendConfig.ini为设置初始参数！\n");
        tipLabel.setBounds(20,5,550,30);
        tipLabel.setFont(font20);

        JLabel filePathLabel = new JLabel("输入CSV故障日志路径: ");
        filePathLabel.setBounds(20,35,550,30);
        filePathLabel.setFont(font16);
//        filePathLabel.setHorizontalAlignment(SwingConstants.CENTER);

        JLabel plcNameLabel = new JLabel("输入监控的PLC名(博图的连接名，多个使用\"/\"分开): ");
        plcNameLabel.setBounds(20,105,550,30);
        plcNameLabel.setFont(font16);

        // 单行文本输入
        // JTextField filePathField = new JTextField();

        // 多行文本输入
        JTextArea filePathField = new JTextArea();
        filePathField.setLineWrap(true); // 设置自动换行
//        filePathField.setBounds(20,65,550,40);
        filePathField.setFont(font16);
        JScrollPane PathscrollPane = new JScrollPane(filePathField);
        PathscrollPane.setBounds(20,65,550,40);
        filePathField.setText(config.getFile());
//        System.out.println(filePathField.getText());

        JTextArea plcNameField = new JTextArea();
        plcNameField.setLineWrap(true); // 设置自动换行
//        plcNameField.setBounds(20,135,550,40);
        JScrollPane PLCscrollPane = new JScrollPane(plcNameField);
        PLCscrollPane.setBounds(20,135,550,40);
        plcNameField.setFont(font16);
        plcNameField.setText(config.getPlcNAME());

        JLabel webhookLabel = new JLabel("输入钉钉机器人webhook");
        webhookLabel.setBounds(20,175,550,30);
        webhookLabel.setFont(font16);

        JTextArea webhookField = new JTextArea();
        webhookField.setLineWrap(true); // 设置自动换行
//        webhookField.setBounds(20,205,550,40);
        JScrollPane webhookscrollPane = new JScrollPane(webhookField);
        webhookscrollPane.setBounds(20,205,550,40);
        webhookField.setFont(font16);
        webhookField.setText(config.getWebhook());

        JLabel secretLabel = new JLabel("输入钉钉机器人secret");
        secretLabel.setBounds(20,245,550,30);
        secretLabel.setFont(font16);

        JTextArea secretField = new JTextArea();
        secretField.setLineWrap(true); // 设置自动换行
//        secretField.setBounds(20,275,550,40);
        JScrollPane secretscrollPane = new JScrollPane(secretField);
        secretscrollPane.setBounds(20,275,550,40);
        secretField.setFont(font16);
        secretField.setText(config.getSecret());

        JLabel MsgClassLabel = new JLabel("过滤不需要的MsgClass");
        MsgClassLabel.setBounds(20,315,550,30);
        MsgClassLabel.setFont(font16);

        JTextField MsgClassField = new JTextField();
        MsgClassField.setBounds(20,345,550,30);
        MsgClassField.setFont(font16);
        MsgClassField.setText(config.getClassNAME());
//        System.out.println(config.getClassNAME());

        JLabel faultLabel = new JLabel("过滤不需要的故障信息(模糊查询，多个使用\"/\"分开): ");
        faultLabel.setBounds(20,375,550,30);
        faultLabel.setFont(font16);

        JTextArea faultField = new JTextArea();
        faultField.setLineWrap(true); // 设置自动换行
//        faultField.setBounds(20,405,550,100);
        JScrollPane faultscrollPane = new JScrollPane(faultField);
        faultscrollPane.setBounds(20,405,550,100);
        faultField.setFont(font16);
        faultField.setText(config.getFaultNAME());
//        System.out.println(config.getFaultNAME());

        JLabel zhuyiLabel = new JLabel("注意：定时备份log文件后清空和定时重启该应用有利该应用高效运行！");
        zhuyiLabel.setBounds(20,505,550,30);
        zhuyiLabel.setFont(font16);

        JTextArea printField = new JTextArea();
        printField.setLineWrap(true); // 设置自动换行
        printField.setEditable(false); //设置为不可编辑
//        printField.setBounds(20,575,550,210);
        JScrollPane printscrollPane = new JScrollPane(printField);
        printscrollPane.setBounds(20,575,550,210);
        printField.setFont(font16);
        printField.setText("");
        // 给按钮添加单击事件监听器
        buttonStart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 在按钮单击事件中启动一个线程执行循环任务
                Thread thread = new Thread(new Runnable() {
                    @Override

                    public void run() {
                        config.setFile(filePathField.getText());
                        config.setPlcNAME(plcNameField.getText());
                        config.setPlcLIST(plcNameField.getText().split("/"));
                        config.setWebhook(webhookField.getText());
                        config.setSecret(secretField.getText());
                        config.setClassNAME(MsgClassField.getText());
                        config.setClasslist(MsgClassField.getText().split("/"));
                        config.setFaultNAME(faultField.getText());
                        config.setFaultlist(faultField.getText().split("/"));
                        String msg1 = "";
                        int count = 0;
                        msg1 = msg1 + "钉钉报警开始运行！  \n" + MyUtils.getDate() +"\n" ;
//                        MyUtils.soutArrary(config.getFaultlist());
                        msg1 = msg1 + "监控以下PLC：\n\t" + config.getPlcNAME()+"\n";
                        msg1 = msg1 + ((!config.getFaultNAME().equals(""))?"以下故障将被屏蔽：\n\t" + config.getFaultNAME()+"\n":"");
//                        System.out.println(12345+msg1);
                        msg1 = msg1 + ((!config.getClassNAME().equals(""))?"屏蔽MsgClass：\n\t"+config.getClassNAME()+"\n":"\n");
                        msg1 = msg1 + "\n" ;
                        printField.insert(msg1,0);
                        if(config.getRepon()!=null&& (config.getFile().equals("") || config.getWebhook().equals("") || config.getSecret().equals("")||config.getPlcNAME().equals(""))){
                            String msg11 =config.getRepon() +MyUtils.getDate()+"\n\n";
                            printField.insert(msg11,0);
                            buttonEnd.doClick();
                        }
                        try {
                            if(!config.getWebhook().equals("") && !config.getSecret().equals("") && !config.getFile().equals("") &&!config.getPlcNAME().equals("")) {
                                DingTalk.DingTalkExample(config, msg1);
                                if(config.getDingdingExceptionErr()!=null){
                                    String msg12 =config.getDingdingExceptionErr()+"\n"+MyUtils.getDate()+"\n\n";
                                    printField.insert(msg12,0);
                                    buttonEnd.doClick();
                                }
                            }else{
                                DingTalk.DingTalkExample(config, msg1);
                                printField.insert("请输入故障日志路径、钉钉机器人的Webhook地址和Secret、PLC名后，再开始!\n\n",0);
                                DingTalk.DingTalkExample(config, "请输入故障日志路径、钉钉机器人的Webhook地址和Secret、PLC名后，再开始!\n\n");
                                buttonEnd.doClick();
                            }
                        } catch (ApiException ex) {
                            throw new RuntimeException(ex);
                        } catch (UnsupportedEncodingException ex) {
                            throw new RuntimeException(ex);
                        } catch (NoSuchAlgorithmException ex) {
                            throw new RuntimeException(ex);
                        } catch (InvalidKeyException ex) {
                            throw new RuntimeException(ex);
                        }
//                        if(config.getAlarmExceptionErr()!=null){
//                            System.out.println(492+config.getAlarmExceptionErr());
//                            String msg11 =config.getAlarmExceptionErr() +MyUtils.getDate()+"\n\n";
//                            printField.insert(msg11,0);
//                            buttonEnd.doClick();
//                        }
                        while (runing[0]) {
//                            count++;
//                            System.out.println("计数值: " + count);
                            try {
                                alarm(config,printField,buttonEnd);
                            } catch (IOException | NoSuchAlgorithmException | InvalidKeyException | ApiException ex) {
//                                throw new RuntimeException(ex);
                            }

                            config.setOnePass(true);
                            try {
                                Thread.sleep(1000); // 每秒输出一次计数值
                            } catch (InterruptedException ex) {
//                        ex.printStackTrace();
                            }
                        }
                    }
                });
                if(!runing[0]) {
                    runing[0] = true;
                    if (!thread.isAlive()) { // 检查线程是否已经启动
                        thread.start(); // 启动线程
                    }
                }
            }
        });
        // 自动触发按钮点击事件
        buttonStart.doClick();
        buttonEnd.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(runing[0]){
                    runing[0] =false;
                    String msg2 = "钉钉报警结束！\n" + MyUtils.getDate()+"\n\n";
                    printField.insert(msg2,0);
                    try {
                        if(!config.getWebhook().equals("") && !config.getSecret().equals("")) {
                            DingTalk.DingTalkExample(config, msg2);
                        }else{
//                        printField.insert("请输入钉钉机器人的Webhook地址和Secret加密\n",0);
                        }
                    } catch (ApiException ex) {
                        throw new RuntimeException(ex);
                    } catch (UnsupportedEncodingException ex) {
                        throw new RuntimeException(ex);
                    } catch (NoSuchAlgorithmException ex) {
                        throw new RuntimeException(ex);
                    } catch (InvalidKeyException ex) {
                        throw new RuntimeException(ex);
                    }
                }

            }
        });
        panel.add(tipLabel);
        panel.add(filePathLabel);
//        panel.add(filePathField);
        // 将滚动面板添加到面板中
        panel.add(PathscrollPane);

        panel.add(plcNameLabel);
        panel.add(PLCscrollPane);
        panel.add(webhookLabel);
        panel.add(webhookscrollPane);
        panel.add(secretLabel);
        panel.add(secretscrollPane);
        panel.add(MsgClassLabel);
        panel.add(MsgClassField);
        panel.add(faultLabel);
        panel.add(faultscrollPane);
        panel.add(zhuyiLabel);
        panel.add(printscrollPane);


        // 将按钮和标签添加到窗口中
        panel.add(buttonStart);
        panel.add(buttonEnd);
//        panel.add(label);

//        panel.setBackground(Color.LIGHT_GRAY);

        // 将JPanel添加到窗口上
        frame.add(panel);
        frame.setVisible(true);

    }

    public static void alarm(configInformation config, JTextArea printField, JButton buttonEnd) throws IOException, NoSuchAlgorithmException, InvalidKeyException, ApiException {
//        System.out.println(741+config.getFile());
        ArrayList<PLC> PLCARR= new ArrayList<>();
        for(String P:config.getPlcLIST()){
            PLC P1 = new PLC(P);
            PLCARR.add(P1);
//                System.out.println(P1.getName());
        }
        try {
            CSVReader reader = new CSVReader(new FileReader(config.getFile(), Charset.forName(config.getEncoding())));
            config.setAlarmExceptionErr(null);
            String[] nextLine;
            String msg = "";
            while ((nextLine = reader.readNext()) != null) {
                // 处理每行数据
//                    System.out.println(nextLine[15]);
//                    for (String cell : nextLine) {
//                        // 处理每个单元格数据
//                        System.out.println(cell);
//                    }
                boolean flag = nextLine[2].equals("1") && !nextLine[0].equals("") && !nextLine[13].equals("") && !(nextLine[13].equals("TimeString")) && !nextLine[14].equals("")  && MyUtils.isdate(nextLine[13]) &&  MyUtils.charinlist(config.getPlcLIST(), nextLine[15]) && !MyUtils.charinlist(config.getClasslist(), nextLine[3]) && !config.getFault1().contains(nextLine[0]);
//                        System.out.println(nextLine[0] +":"+ flag);
                if (flag) {
//                    System.out.println("新故障："+ nextLine[14]);
                    ArrayList<String> AA = new ArrayList<>();
                    for(String ELE:nextLine) AA.add(ELE);
                    if(config.isOnePass()) {
                        boolean lemp1 = true;
//                        MyUtils.soutArrary(List.of(config.getFaultlist()));
                        for (String ii : config.getFaultlist()) {
                            if (!ii.equals("") && nextLine[14].contains(ii)) {
                                lemp1 = false;
                            }
                        }
//                        System.out.println(lemp1);
                        if(lemp1) {
                            for (PLC PP : PLCARR) {
                                if (PP.getName().equals(nextLine[15])) {
                                    PP.addLIST1(AA);
//                                    MyUtils.soutArrary(PP.getLIST1());
                                    //                                        System.out.println(PP.getLIST1());
                                }
                            }
                        }
                    }
                    config.addFault1(nextLine[0]);
                }
//                        System.out.println(nextLine[0]+":== " + nextLine[2].equals("0") + " + " + !nextLine[0].equals("") + " + "  + !nextLine[13].equals("") + " + "  + !(nextLine[13].equals("TimeString")) + " + "  + !nextLine[14].equals("") + " + "   + MyUtils.isdate(nextLine[13]) + " + "   + MyUtils.charinlist(plcLIST, nextLine[15]) + " + "  + !MyUtils.charinlist(classlist, nextLine[3]) + " + "  + !reset1.contains(nextLine[0] ));
                boolean flag2 = nextLine[2].equals("0") && !nextLine[0].equals("") && !nextLine[13].equals("") && !(nextLine[13].equals("TimeString")) && !nextLine[14].equals("")  && MyUtils.isdate(nextLine[13])  && MyUtils.charinlist(config.getPlcLIST(), nextLine[15]) && !MyUtils.charinlist(config.getClasslist(), nextLine[3]) && !config.getReset1().contains(nextLine[0]);
//                        System.out.println(nextLine[0]+": " + flag2);
                if (flag2) {
//                    System.out.println("复位："+nextLine[14]);
                    ArrayList<String> BB = new ArrayList<>();
                    for(String ELE:nextLine) BB.add(ELE);
                    if(config.isOnePass()) {
                        boolean lemp1 = true;
//                        MyUtils.soutArrary(config.getFaultlist());
                        for (String ii : config.getFaultlist()) {
                            if (!ii.equals("") && nextLine[14].contains(ii)) {
                                lemp1 = false;
                            }
                        }
                        if(lemp1) {
                            for (PLC PP : PLCARR) {
                                if (PP.getName().equals(nextLine[15])) {
                                    PP.addLIST2(BB);
                                }
                            }
                        }
//                                data2.add(BB);
                    }
                    config.addReset1(nextLine[0]);
                }
            }
            for(PLC PP:PLCARR){
//                System.out.println(PP.getName()+" : " + PP.getsize1());
                if(PP.getsize1()>0){
                    msg = msg+"----------报警信息----------\n"+ MyUtils.getDate()+"\n"  + PP.getName() +"：\n";
//                            System.out.println(msg);
                    List<List<String>> LIST11 = PP.getLIST1();
//                           // 外部循环遍历每个外部List
                    for (List<String> innerList1 : LIST11) {
                        // 内部循环遍历每个内部List
                        msg = msg + innerList1.get(14)+ "\n" + innerList1.get(13)+ "\n\n";
                    }
                }
                if(PP.getsize2()>0){
                    msg = msg+"----------复位信息----------\n"+ MyUtils.getDate()+"\n"  + PP.getName() +"：\n";
//                            System.out.println(msg);
                    List<List<String>> LIST22 = PP.getLIST2();
//                           // 外部循环遍历每个外部List
                    for (List<String> innerList2 : LIST22) {
                        // 内部循环遍历每个内部List
                        msg = msg + innerList2.get(14)+ "\n" + innerList2.get(13)+ "\n\n";
                    }
                }

                PP.setLIST1(new ArrayList<>());
                PP.setLIST2(new ArrayList<>());
            }
            if(!msg.equals("")){
                msg = msg + "================\n";
//                System.out.println(msg);
                printField.insert(msg,0);
                DingTalk.DingTalkExample(config,msg);
            }
            reader.close();
        } catch(Exception e){
            String ERR = e+"\n\n";
            printField.insert(ERR,0);
            DingTalk.DingTalkExample(config, ERR);
            config.setAlarmExceptionErr(ERR);
            buttonEnd.doClick();
        }
//        try {
//            // 可能抛出 InterruptedException 异常的代码
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {e.printStackTrace();}
    }
}

